/*******************************************************************************

  Pilot Intelligence Library
    http://www.pilotintelligence.com/

  ----------------------------------------------------------------------------

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.

*******************************************************************************/

#ifndef __MISSIONDATA_TRANSFER__
#define __MISSIONDATA_TRANSFER__

#include <stdint.h>

#include <string>
#include <vector>
#include <deque>

#include <base/osa/osa++.h>
#include <network/Socket++.h>


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

struct MissionData_Simp
{
public:
    enum MissionType {
        MT_WAYPOINT             = 0,                ///< waypoint
        MT_START_MISSION        = 1001,             ///< start mission
        MT_STOP_MISSION         = 1002,             ///< stop mission
    };

public:
    // misc information
    uint32_t    version;                            ///< protocol version

    // UAV information
    uint32_t    uavID;                              ///< UAV ID number

    // mission number / index
    uint32_t    missionNum;                         ///< total mission number
    uint32_t    missionIdx;                         ///< this mission index

    // position and attitude
    double      lat;                                ///< latitude
    double      lng;                                ///< longitude
    double      alt;                                ///< alititude (above ground - home altitude)

    uint32_t    missionType;                        ///< mission type
                                                    ///<    MT_WAYPOINT         - waypoint
                                                    ///<    MT_START_MISSION    - start mission (start with given missionIdx)
                                                    ///<    MT_STOP_MISSION     - stop mission

    // CRC
    uint8_t     crc[8];

public:
    MissionData_Simp() {
        uint8_t *p = (uint8_t*) this;
        memset(p, 0, sizeof(this));
    }

    int calcCRC(void) {
        uint8_t *p = (uint8_t*) this;

        int n = sizeof(this) - 8;
        int sum = 0;

        for(int i=0; i<n; i++) {
            sum += p[i];
        }

        sum = sum % 256;
        crc[0] = sum;

        return 0;
    }

    int checkCRC(void) {
        uint8_t *p = (uint8_t*) this;

        int n = sizeof(this) - 8;
        int sum = 0;

        for(int i=0; i<n; i++) {
            sum += p[i];
        }

        sum = sum % 256;
        if( sum != crc[0] ) return -1;
        else return 0;
    }

    int print(void) {
        printf("MISSION[%3d] ID/NUM = %5d/%5d, Type = %5d, protocol version: %d\n",
                        uavID, missionIdx, missionNum, missionType, version);
        printf("    lat, lng, alt = %12f, %12f : %12f\n",
                        lat, lng, alt);

        return 0;
    }
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

typedef std::vector<MissionData_Simp> MissionDataArray;             ///< mission array



////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class MissionData_Transfer : public pi::Thread
{
public:
    MissionData_Transfer();
    virtual ~MissionData_Transfer();

    virtual void threadFunc();
    virtual void stop(void);

    int begin(const std::string &addr, int port, int isServer=1);
    int isRunning(void) { return m_bOpened; }

    int sendMission(MissionData_Simp *m);
    int recvMission(MissionData_Simp *m);

private:
    pi::RSocket                     m_socket;                   ///< socket obj
    int                             m_bOpened;                  ///< socket opened?
    int                             m_isServer;                 ///< server/client

    std::deque<MissionData_Simp>    m_misQueue;                 ///< mission queue

    pi::Mutex                       m_mutex;
};

#endif // end of __MISSIONDATA_TRANSFER__
